import * as Cesium from "cesium";

export default class GridCell {

  // 存储键- 索引的映射 - 用于快速查找立方体 (O(1)查找优化)
  GridCellMap = new Map()

  // 存储网格单元实体数据
  GridCellLayer = []

  // 添加当前层索引指针
  currentLayerIndex = 0

  // 添加当前无人机位置跟踪
  currentUAVLayer = null

  // 优化：使用单一primitive存储所有立方体
  gridPrimitive = null
  edgePrimitive = null

  constructor(viewer, position, size = 15.0) {
    this.viewer = viewer;
    this.position = position;
    // 立方体大小
    this.halfSize = size / 2;
    // 将[经度,纬度,高度]数组转换为Cartesian3对象
    const cartesian = Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      position[2]
    );
    // 创建一个局部坐标系的变换矩阵，防止因地球曲率导致的变形
    const hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
    const orientation = Cesium.Transforms.headingPitchRollQuaternion(
      cartesian,
      hpr
    );
    this.modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
      cartesian, // 平移
      orientation, // 旋转
      new Cesium.Cartesian3(1, 1, 1) // 缩放
    );

    // 重新计算逆矩阵
    this.inverseMatrix = Cesium.Matrix4.inverse(
      this.modelMatrix,
      new Cesium.Matrix4()
    );

    this.allColor = {
      // 异常
      Red: new Cesium.Color(1.0, 0.0, 0.0, 0.3),
      // 警告
      Yellow: new Cesium.Color(1.0, 1.0, 0.0, 0.3),
      // 计划
      Green: new Cesium.Color(0.5, 1.0, 0.5, 0.3),
      // 当前网格 - 自定义绿色高亮 RGB(50, 205, 50)
      DarkGreen: new Cesium.Color(0.0, 1.0, 0.0, 0.3),
      // 正常
      White: new Cesium.Color(1.0, 1.0, 1.0, 0.3),
    };

    // 启用场景抗锯齿
    this.viewer.scene.postProcessStages.fxaa.enabled = false;
    // 初始化几何数据
    this.initGeometryData();
    // 初始化基础立方体几何
    this.initBaseCubeGeometry();
  }

  initGeometryData () {
    // 基础层(底部立方体)使用白色
    const baseLayer = {
      color: "White",
      keyIndex: [0, 0, 0],
      show: true,
    };

    // 优化：同步更新数据结构
    this.GridCellLayer = [baseLayer];
    // O(1) 快速查找：keyIndex -> layer索引映射
    this.GridCellMap.set(this.keyIndexToString([0, 0, 0]), 0);
  }

  /**
   * 初始化基础立方体几何数据
   */
  initBaseCubeGeometry () {
    // 顶点坐标
    this.basePositions = new Float64Array([
      -this.halfSize, -this.halfSize, -this.halfSize, // 0
      this.halfSize, -this.halfSize, -this.halfSize,  // 1
      this.halfSize, this.halfSize, -this.halfSize,   // 2
      -this.halfSize, this.halfSize, -this.halfSize,  // 3
      -this.halfSize, -this.halfSize, this.halfSize,  // 4
      this.halfSize, -this.halfSize, this.halfSize,   // 5
      this.halfSize, this.halfSize, this.halfSize,    // 6
      -this.halfSize, this.halfSize, this.halfSize,   // 7
    ]);

    // 索引
    this.baseIndices = new Uint16Array([
      0, 1, 2, 0, 2, 3, // 底面
      4, 5, 6, 4, 6, 7, // 顶面
      0, 1, 5, 0, 5, 4, // 前面
      1, 2, 6, 1, 6, 5, // 右面
      2, 3, 7, 2, 7, 6, // 后面
      3, 0, 4, 3, 4, 7, // 左面
    ]);

    // 边缘线索引
    this.edgeIndices = new Uint16Array([
      // 底面四条边
      0, 1, 1, 2, 2, 3, 3, 0,
      // 顶面四条边
      4, 5, 5, 6, 6, 7, 7, 4,
      // 连接顶面和底面的四条边
      0, 4, 1, 5, 2, 6, 3, 7,
    ]);
  }

  /**
   * 将 keyIndex 数组转换为字符串键，用于 Map 存储
   * @param {Array} keyIndex - 三维索引数组 [x, y, z]
   * @returns {String} - 字符串键
   */
  keyIndexToString (keyIndex) {
    return `${keyIndex[0]}_${keyIndex[1]}_${keyIndex[2]}`;
  }

  // 向指定方向添加一个立方体 (优化版本 - O(1)查找)
  extend (direction, offset = 1, color) {
    // 获取当前基准层的立方体数据（使用指针而不是数组最后一个元素）
    const currentLayer = this.GridCellLayer[this.currentLayerIndex];
    const lastKeyIndex = currentLayer.keyIndex || [0, 0, 0]; // 获取当前基准层的keyIndex

    // 方向映射：统一处理方向逻辑
    const directionMap = {
      "1_0_0": { axis: 0, sign: 1 },   // 向左时第一个元素+1
      "-1_0_0": { axis: 0, sign: -1 }, // 向右时第一个元素-1
      "0_1_0": { axis: 1, sign: 1 },   // 向前时第二个元素+1
      "0_-1_0": { axis: 1, sign: -1 }, // 向后时第二个元素-1
      "0_0_1": { axis: 2, sign: 1 },   // 向上时第三个元素+1
      "0_0_-1": { axis: 2, sign: -1 }  // 向下时第三个元素-1
    };

    const dirInfo = directionMap[direction];
    if (!dirInfo) {
      console.warn("无效的方向:", direction);
      return this;
    }

    // 根据方向更新keyIndex
    const newKeyIndex = [...lastKeyIndex];
    newKeyIndex[dirInfo.axis] = lastKeyIndex[dirInfo.axis] + dirInfo.sign;

    // 优化：使用Map进行O(1)查找，检查是否已存在具有相同keyIndex的层
    const keyString = this.keyIndexToString(newKeyIndex);
    const existingLayerIndex = this.GridCellMap.get(keyString);

    // 如果存在相同keyIndex的层，只更新颜色并更新当前指针
    if (existingLayerIndex !== undefined) {
      this.GridCellLayer[existingLayerIndex].color = color;
      this.GridCellLayer[existingLayerIndex].show = true;

      // 更新当前层指针到找到的层，这样下次extend就会基于这个层
      this.currentLayerIndex = existingLayerIndex;

      // 重新绘制
      this.drawBox();
      return this;
    }

    // 计算立方体中心点的世界坐标
    const cubeSize = this.halfSize * 2;
    const cubeLocalCenter = new Cesium.Cartesian3(
      -newKeyIndex[0] * cubeSize,  // 注意坐标系方向
      -newKeyIndex[1] * cubeSize,
      newKeyIndex[2] * cubeSize
    );

    const worldCenter = Cesium.Matrix4.multiplyByPoint(
      this.modelMatrix,
      cubeLocalCenter,
      new Cesium.Cartesian3()
    );
    const cartographic = Cesium.Cartographic.fromCartesian(worldCenter);
    const centerLLA = [
      Cesium.Math.toDegrees(cartographic.longitude),
      Cesium.Math.toDegrees(cartographic.latitude),
      cartographic.height,
    ];

    // 创建新层对象
    const newLayer = {
      color: color,
      show: true,
      keyIndex: newKeyIndex,
      centerPoint: centerLLA,
    };

    // 优化：同步更新两个数据结构
    const newLayerIndex = this.GridCellLayer.length;
    this.GridCellLayer.push(newLayer);
    this.GridCellMap.set(keyString, newLayerIndex);

    // 更新当前层指针到新添加的层
    this.currentLayerIndex = newLayerIndex;

    // 重新绘制
    this.drawBox();
    return this;
  }

  // 销毁所有primitives
  destroy () {
    // 移除主要的网格primitive
    if (this.gridPrimitive && !this.gridPrimitive.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.gridPrimitive);
    }

    // 移除边缘线primitive
    if (this.edgePrimitive && !this.edgePrimitive.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.edgePrimitive);
    }

    // 重置primitive引用
    this.gridPrimitive = null;
    this.edgePrimitive = null;
  }

  // 重置GridCell，销毁所有primitives并重置几何数据
  reset (position) {
    // 销毁所有primitives
    this.destroy();

    // 优化：重置数据结构
    this.GridCellLayer = [];
    this.GridCellMap.clear();

    // 重置当前层指针
    this.currentLayerIndex = 0;

    // 重置当前无人机位置跟踪
    this.currentUAVLayer = null;

    // 如果传入position，重置中心坐标和矩阵
    if (position) {
      this.position = position;
      const cartesian = Cesium.Cartesian3.fromDegrees(
        position[0],
        position[1],
        position[2]
      );
      const hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        cartesian,
        hpr
      );
      this.modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
        cartesian, // 平移
        orientation, // 旋转
        new Cesium.Cartesian3(1, 1, 1) // 缩放
      );

      // 重新计算逆矩阵
      this.inverseMatrix = Cesium.Matrix4.inverse(
        this.modelMatrix,
        new Cesium.Matrix4()
      );
    }

    // 重新初始化几何数据
    this.initGeometryData();

    return this;
  }

  /**
   * 使用InstancedGeometry优化的绘制方法
   * 将所有立方体合并到一个primitive中
   */
  drawBox () {
    // 销毁旧的primitives
    this.destroy();

    // 创建几何实例数组
    const geometryInstances = [];

    // 为每个显示的立方体创建一个GeometryInstance
    this.GridCellLayer.forEach((layer, index) => {
      // 检查该方格是否需要显示
      if (layer.show === false) {
        return;
      }

      // 计算立方体的变换矩阵
      const cubeSize = this.halfSize * 2;
      const cubeLocalCenter = new Cesium.Cartesian3(
        -layer.keyIndex[0] * cubeSize,
        -layer.keyIndex[1] * cubeSize,
        layer.keyIndex[2] * cubeSize
      );

      // 创建变换矩阵
      const cubeMatrix = Cesium.Matrix4.multiplyByTranslation(
        this.modelMatrix,
        cubeLocalCenter,
        new Cesium.Matrix4()
      );

      // 获取颜色
      const cesiumColor = this.allColor[layer.color] || this.allColor.White;

      // 创建立方体几何实例
      const geometryInstance = new Cesium.GeometryInstance({
        geometry: new Cesium.Geometry({
          attributes: {
            position: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.DOUBLE,
              componentsPerAttribute: 3,
              values: this.basePositions,
            }),
          },
          indices: this.baseIndices,
          primitiveType: Cesium.PrimitiveType.TRIANGLES,
          boundingSphere: Cesium.BoundingSphere.fromVertices(this.basePositions),
        }),
        modelMatrix: cubeMatrix,
        id: `cube_${index}`,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(cesiumColor)
        }
      });

      geometryInstances.push(geometryInstance);
    });

    // 如果有几何实例，创建primitive
    if (geometryInstances.length > 0) {
      this.gridPrimitive = new Cesium.Primitive({
        geometryInstances: geometryInstances,
        appearance: new Cesium.PerInstanceColorAppearance({
          flat: true,
          translucent: true,
          vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
        }),
        asynchronous: false,
        releaseGeometryInstances: false,
        renderState: {
          depthTest: {
            enabled: true,
          },
          depthMask: false,
          blending: Cesium.BlendingState.ALPHA_BLEND,
        },
      });

      this.viewer.scene.primitives.add(this.gridPrimitive);
    }

    // 创建边缘线
    this.createEdgesPrimitive();

    return {
      gridPrimitive: this.gridPrimitive,
      edgePrimitive: this.edgePrimitive,
    };
  }

  /**
   * 创建立方体边缘线
   */
  createEdgesPrimitive () {
    const edgeGeometryInstances = [];

    // 为每个显示的立方体创建边缘线几何实例
    this.GridCellLayer.forEach((layer, index) => {
      if (layer.show === false) {
        return;
      }

      // 计算立方体的变换矩阵
      const cubeSize = this.halfSize * 2;
      const cubeLocalCenter = new Cesium.Cartesian3(
        -layer.keyIndex[0] * cubeSize,
        -layer.keyIndex[1] * cubeSize,
        layer.keyIndex[2] * cubeSize
      );

      const cubeMatrix = Cesium.Matrix4.multiplyByTranslation(
        this.modelMatrix,
        cubeLocalCenter,
        new Cesium.Matrix4()
      );

      // 获取颜色（边缘线使用相同颜色但不透明）
      const cesiumColor = this.allColor[layer.color] || this.allColor.White;
      const edgeColor = new Cesium.Color(cesiumColor.red, cesiumColor.green, cesiumColor.blue, 1.0);

      // 创建边缘线几何
      const edgeGeometry = new Cesium.Geometry({
        attributes: {
          position: new Cesium.GeometryAttribute({
            componentDatatype: Cesium.ComponentDatatype.DOUBLE,
            componentsPerAttribute: 3,
            values: this.basePositions,
          }),
        },
        indices: this.edgeIndices,
        primitiveType: Cesium.PrimitiveType.LINES,
        boundingSphere: Cesium.BoundingSphere.fromVertices(this.basePositions),
      });

      const edgeInstance = new Cesium.GeometryInstance({
        geometry: edgeGeometry,
        modelMatrix: cubeMatrix,
        id: `edge_${index}`,
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(edgeColor)
        }
      });

      edgeGeometryInstances.push(edgeInstance);
    });

    // 创建边缘线primitive
    if (edgeGeometryInstances.length > 0) {
      this.edgePrimitive = new Cesium.Primitive({
        geometryInstances: edgeGeometryInstances,
        appearance: new Cesium.PerInstanceColorAppearance({
          flat: true,
          translucent: false,
          vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
          renderState: {
            lineWidth: Math.min(2.0, this.viewer.scene.maximumAliasedLineWidth),
            depthTest: {
              enabled: true,
            },
            depthMask: true,
          },
        }),
        asynchronous: false,
        releaseGeometryInstances: false,
        allowPicking: false,
      });

      this.viewer.scene.primitives.add(this.edgePrimitive);
    }
  }

  /**
   * 根据MQTT传入的经纬度点位计算与中心点的偏移量
   * @param {Array} mqttPosition - MQTT传入的经纬度点位 [longitude, latitude, height]
   * @returns {Array} - 返回一个三元素数组 [左右偏移量,前后偏移量,上下偏移量]
   */
  getKeyIndexByLLA (mqttPosition) {
    // 将目标点转换为Cartesian3坐标
    const targetCartesian = Cesium.Cartesian3.fromDegrees(
      mqttPosition[0],
      mqttPosition[1],
      mqttPosition[2] || 0
    );

    // 计算目标点在模型局部坐标系中的位置
    const localPosition = Cesium.Matrix4.multiplyByPoint(
      this.inverseMatrix,
      targetCartesian,
      new Cesium.Cartesian3()
    );

    // 计算网格单元尺寸
    const gridUnitSize = this.halfSize * 2;

    // 计算网格偏移量（注意坐标系方向）
    const leftRightOffset = Math.round(-localPosition.x / gridUnitSize);
    const frontBackOffset = Math.round(-localPosition.y / gridUnitSize);
    const upDownOffset = Math.round(localPosition.z / gridUnitSize);
    return [leftRightOffset, frontBackOffset, upDownOffset];
  }

  /**
   * 根据偏移量数组添加立方体
   * @param {Array} offsetsArray - 偏移量数组 [左右偏移量,前后偏移量,上下偏移量]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  extendByOffsets (offsetsArray, color) {
    if (!Array.isArray(offsetsArray) || offsetsArray.length !== 3) {
      console.error(
        "偏移量数组格式不正确，应为[左右偏移量,前后偏移量,上下偏移量]"
      );
      return this;
    }

    // 遍历三个方向的偏移量
    offsetsArray.forEach((offset, index) => {
      if (offset === 0) return; // 如果偏移量为0，跳过此方向

      // 创建方向字符串，例如 '1_0_0', '0_1_0', '0_0_1'
      let direction = [0, 0, 0];
      direction[index] = offset > 0 ? 1 : -1; // 根据偏移量正负设置方向
      const directionString = direction.join("_");

      // 根据偏移量的绝对值添加多个立方体
      const absOffset = Math.abs(offset);
      for (let i = 0; i < absOffset; i++) {
        this.extend(directionString, 1, color);
      }
    });

    return this;
  }

  /**
  * 改变方格的颜色 (优化版本 - O(1)查找)
  * @param {Object} options - 配置对象
  * @param {Array} options.position - 经纬度数组 [longitude, latitude, height]
  * @param {String} options.color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
  * @param {Boolean} options.isGridColor - 是否使用网格颜色，为true时使用DarkGreen
  * @param {Number} options.mode - 模式，0为默认模式，1为批量更新模式
  * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
  */
  changeColor (options = {}) {
    const { position, color, isGridColor = false, mode = 0 } = options;

    // 坐标转换 - 将经纬度转换为局部坐标系
    const posCartesian = Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      position[2] || 0
    );

    const localPoint = Cesium.Matrix4.multiplyByPoint(
      this.inverseMatrix,
      posCartesian,
      new Cesium.Cartesian3()
    );

    // 如果是无人机位置更新，先清除之前的无人机位置颜色
    if (isGridColor && this.currentUAVLayer) {
      this.currentUAVLayer.color = color;
      this.currentUAVLayer = null;
    }

    // 精确空间位置匹配 - 遍历所有立方体，找到包含目标点的立方体
    let targetLayer = null;
    let needsRedraw = false;

    for (const layer of this.GridCellLayer) {
      if (!layer.keyIndex) continue;

      if (this.isPointInCube(localPoint, layer)) {
        targetLayer = layer;
        break;
      } else if (mode && layer.color !== color) {
        // mode为1时，批量更新其他方格颜色
        layer.color = color;
        needsRedraw = true;
      }
    }

    // 更新找到的立方体颜色
    if (targetLayer) {
      const finalColor = isGridColor ? 'DarkGreen' : color;

      if (targetLayer.color !== finalColor || targetLayer.show === false) {
        // 如果是无人机位置，更新当前无人机位置引用
        if (isGridColor) {
          this.currentUAVLayer = targetLayer;
        }

        targetLayer.color = finalColor;
        targetLayer.show = true;
        needsRedraw = true;
      }
    } else {
      console.warn(`精确匹配失败: 未找到坐标 [${position}] 对应的方格`);
    }

    // 只有在需要时才重新绘制
    if (needsRedraw) {
      this.drawBox();
    }

    return this;
  }

  /**
   * 加载网格数据json，绘制整个网格
   * @param {Array} jsonData - 网格数据数组，每个元素包含经纬度坐标 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
   * @param {Boolean} fillGaps - 是否填充空隙，true为补全模式，false为不补全模式，默认true
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  loadGridDataJson (jsonData, color = 'White', fillGaps = true) {

    // 如果已有图层，重置到第一个点位作为新的中心点
    if (this.GridCellLayer.length > 0) {
      // 重置到第一个点位作为新的中心点
      this.reset(jsonData[0]);
    }

    const optimizedData = jsonData;

    // 修复：添加变量跟踪上一个逻辑点的keyIndex，避免依赖会被extend修改的currentLayerIndex
    let lastLogicalKeyIndex = [0, 0, 0]; // 第一个点的keyIndex

    // 统一循环处理所有点位数据
    for (let i = 0; i < optimizedData.length; i++) {
      const pointData = optimizedData[i];

      // 验证点位数据格式
      if (!Array.isArray(pointData) || pointData.length < 2) {
        console.warn(`跳过无效的点位数据: ${pointData}`);
        continue;
      }

      // 确保有高度值，如果没有则使用0
      const position = [
        pointData[0], // longitude
        pointData[1], // latitude
        pointData.length > 2 ? pointData[2] : 0 // height
      ];

      // 第一个点位作为中心点，不需要计算偏移
      if (i === 0) {
        // 基础层已经在reset或初始化时创建，只需要设置颜色
        if (this.GridCellLayer.length > 0) {
          this.GridCellLayer[0].color = color;
        }
        continue;
      }

      // 根据fillGaps参数选择不同的处理方式
      if (fillGaps) {
        // 补全模式：计算偏移量并使用extendByOffsets
        // 修复：使用跟踪的上一个逻辑点keyIndex，而不是currentLayerIndex
        const diffIndexXYZ1 = lastLogicalKeyIndex;
        const diffIndexXYZ2 = this.getKeyIndexByLLA(position);

        const offsets = [
          diffIndexXYZ2[0] - diffIndexXYZ1[0], // x偏移
          diffIndexXYZ2[1] - diffIndexXYZ1[1], // y偏移
          diffIndexXYZ2[2] - diffIndexXYZ1[2], // z偏移
        ];

        // 根据偏移量添加立方体
        this.extendByOffsets(offsets, color);

        // 修复：更新lastLogicalKeyIndex为当前点的keyIndex
        lastLogicalKeyIndex = [...diffIndexXYZ2];
      } else {
        // 不补全模式：直接在指定位置创建立方体，不进行补全
        this.createCubeAtPosition(position, color);
      }
    }

    // 重新绘制
    this.drawBox();

    return this;
  }

  /**
   * 绘制单个方格
   * @param {Array} position - 经纬度数组 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'DarkGreen', 'White'
   * @param {Boolean} fillGaps - 是否填充空隙，true为补全模式，false为不补全模式，默认true
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  drawSingleBox (position, color = 'White', fillGaps = true) {

    // 确保有高度值，如果没有则使用0
    const normalizedPosition = [
      position[0], // longitude
      position[1], // latitude
      position.length > 2 ? position[2] : 0 // height
    ];

    // 如果没有图层，先创建基础图层
    if (this.GridCellLayer.length === 0) {
      console.warn("没有基础图层，请先初始化GridCell或加载网格数据");
      return this;
    }

    // 根据 fillGaps 参数选择不同的处理方式
    if (fillGaps) {
      // 补全模式：计算偏移量并使用extendByOffsets
      // 直接从 this.GridCellLayer 数组中获取第一个网格
      const firstLayer = this.GridCellLayer[0];
      if (firstLayer && firstLayer.color === 'White') {
        firstLayer.color = color;
      }

      // 计算当前基准层的keyIndex和目标位置的keyIndex
      const currentKeyIndex = this.GridCellLayer[this.currentLayerIndex].keyIndex;
      const targetKeyIndex = this.getKeyIndexByLLA(normalizedPosition);

      // 计算偏移量
      const xOffset = targetKeyIndex[0] - currentKeyIndex[0]; // 左右方向偏移
      const yOffset = targetKeyIndex[1] - currentKeyIndex[1]; // 前后方向偏移
      const zOffset = targetKeyIndex[2] - currentKeyIndex[2]; // 上下方向偏移

      // 根据偏移量添加立方体
      this.extendByOffsets([xOffset, yOffset, zOffset], color);
    } else {
      // 不补全模式：直接在指定位置创建立方体，不进行补全
      this.createCubeAtPosition(normalizedPosition, color);
    }

    // 重新绘制
    this.drawBox();

    return this;
  }

  /**
   * 在指定位置直接创建立方体（不补全中间的空隙）(优化版本)
   * @param {Array} position - 经纬度数组 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'DarkGreen', 'White'
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  createCubeAtPosition (position, color = 'White') {
    // 确保有高度值，如果没有则使用0
    const normalizedPosition = [
      position[0], // longitude
      position[1], // latitude
      position.length > 2 ? position[2] : 0 // height
    ];

    // 计算目标位置的keyIndex
    const targetKeyIndex = this.getKeyIndexByLLA(normalizedPosition);
    const keyString = this.keyIndexToString(targetKeyIndex);

    // 优化：使用Map进行O(1)查找，检查是否已存在具有相同keyIndex的层
    const existingLayerIndex = this.GridCellMap.get(keyString);

    // 如果存在相同keyIndex的层，只更新颜色
    if (existingLayerIndex !== undefined) {
      this.GridCellLayer[existingLayerIndex].color = color;
      this.GridCellLayer[existingLayerIndex].show = true;
      return this;
    }

    // 计算立方体中心点的世界坐标
    const cubeSize = this.halfSize * 2;
    const cubeLocalCenter = new Cesium.Cartesian3(
      -targetKeyIndex[0] * cubeSize,  // 注意坐标系方向
      -targetKeyIndex[1] * cubeSize,
      targetKeyIndex[2] * cubeSize
    );

    const worldCenter = Cesium.Matrix4.multiplyByPoint(
      this.modelMatrix,
      cubeLocalCenter,
      new Cesium.Cartesian3()
    );
    const cartographic = Cesium.Cartographic.fromCartesian(worldCenter);
    const centerLLA = [
      Cesium.Math.toDegrees(cartographic.longitude),
      Cesium.Math.toDegrees(cartographic.latitude),
      cartographic.height,
    ];

    // 创建新层对象
    const newLayer = {
      color: color,
      show: true,
      keyIndex: targetKeyIndex,
      centerPoint: centerLLA,
    };

    // 优化：同步更新两个数据结构
    const newLayerIndex = this.GridCellLayer.length;
    this.GridCellLayer.push(newLayer);
    this.GridCellMap.set(keyString, newLayerIndex);

    return this;
  }

  /**
   * 判断一个点是否在立方体内部（优化版本）
   * @param {Cesium.Cartesian3} localPoint - 目标点在局部坐标系中的坐标（预计算）
   * @param {Object} layer - 立方体图层对象
   * @returns {Boolean} - 点是否在立方体内
   */
  isPointInCube (localPoint, layer) {
    // 获取立方体的大小
    const cubeSize = this.halfSize * 2;

    // 根据keyIndex计算立方体中心在局部坐标系中的位置
    const cubeCenter = new Cesium.Cartesian3(
      -layer.keyIndex[0] * cubeSize,  // 注意坐标系方向与keyIndex的关系
      -layer.keyIndex[1] * cubeSize,
      layer.keyIndex[2] * cubeSize
    );

    // 计算立方体的边界范围
    const minX = cubeCenter.x - this.halfSize;
    const maxX = cubeCenter.x + this.halfSize;
    const minY = cubeCenter.y - this.halfSize;
    const maxY = cubeCenter.y + this.halfSize;
    const minZ = cubeCenter.z - this.halfSize;
    const maxZ = cubeCenter.z + this.halfSize;

    // 判断点是否在立方体内（包括边界）
    const isInside =
      localPoint.x >= minX && localPoint.x <= maxX &&
      localPoint.y >= minY && localPoint.y <= maxY &&
      localPoint.z >= minZ && localPoint.z <= maxZ;

    return isInside;
  }
} 